# excel_writer.py
import openpyxl
from pathlib import Path
from typing import List, Dict, Optional, Union, Any
from concurrent.futures import ThreadPoolExecutor
from openpyxl.worksheet.worksheet import Worksheet

from config.path import path_manager
from config.project_info import PROJECT_BASE_INFO


class DirectTemplateWriter:
    def __init__(self, data: List[Dict], group_by: Optional[str] = None):
        """
        初始化模板写入器

        :param data: 待写入的数据列表（格式：[{'cell_ref': 'B12', 'value': 'xxx', 'sheet': 'JS101', ...}]）
        :param group_by: 分组字段（如 'group_key'），用于区分同一 sheet 的不同实例
        """
        self.data = data
        self.group_by = group_by
        self._validate_input()
        self.template_groups = self._group_by_sheet()

    def _validate_input(self) -> None:
        required_keys = {"cell_ref", "value", "sheet"}
        for idx, item in enumerate(self.data):
            missing = required_keys - set(item.keys())
            if missing:
                raise ValueError(f"数据项{idx}缺少必要字段: {missing}")

    def _group_by_sheet(self) -> Dict[str, Union[List[Dict], Dict[str, List[Dict]]]]:
        groups = {}
        for item in self.data:
            sheet = item["sheet"]
            if sheet not in groups:
                groups[sheet] = {}

            if self.group_by:
                group_key = item.get(self.group_by)
                if not group_key:
                    raise ValueError(f"缺少分组字段 {self.group_by}")
                if group_key not in groups[sheet]:
                    groups[sheet][group_key] = []
                groups[sheet][group_key].append(item)
            else:
                if not isinstance(groups[sheet], list):
                    groups[sheet] = []
                groups[sheet].append(item)

        return groups

    def write_all(
        self,
        max_workers: int = 4,
        sheet_order: Optional[List[str]] = None,
        output_suffix: Optional[str] = None,
        sub_dir: Optional[str] = None
    ) -> List[str]:
        results = []
        order_map = {sheet: idx for idx, sheet in enumerate(sheet_order or list(self.template_groups.keys()))}

        with ThreadPoolExecutor(max_workers=max_workers) as executor:
            futures = []
            for sheet_name, group_data in self.template_groups.items():
                sheet_idx = order_map.get(sheet_name, len(order_map))

                if self.group_by:
                    # 多个实例的情况
                    for group_key, instance_data in group_data.items():
                        suffix = f"{output_suffix}_{group_key}" if output_suffix else group_key
                        future = executor.submit(
                            self._process_single_template,
                            sheet_name=sheet_name,
                            group_data=instance_data,
                            sheet_idx=sheet_idx,
                            output_suffix=suffix,
                            sub_dir=sub_dir
                        )
                        futures.append((future, sheet_name))
                else:
                    # 单个实例的情况
                    future = executor.submit(
                        self._process_single_template,
                        sheet_name=sheet_name,
                        group_data=group_data,
                        sheet_idx=sheet_idx,
                        output_suffix=output_suffix,
                        sub_dir=sub_dir
                    )
                    futures.append((future, sheet_name))

            for future, sheet_name in futures:
                result = future.result()
                results.append(result)
                print(result)

        return results

    @staticmethod
    def _process_single_template(
        sheet_name: str,
        group_data: List[Dict],
        sheet_idx: int,
        output_suffix: Optional[str],
        sub_dir: Optional[str] = None
    ) -> str:
        try:
            construction_site = group_data[0].get('project_info', {}).get('施工部位', '未知施工部位')

            base_filename = f"{sheet_idx + 1:02d} {construction_site}_{sheet_name}"

            
            if output_suffix:
               base_filename += f"_{output_suffix}"

            template_path = path_manager.get_template_path(sheet_name)
            if not template_path.exists():
                raise FileNotFoundError(f"模板文件不存在（请检查templates目录是否有{sheet_name}.xlsx）")

            wb = openpyxl.load_workbook(template_path)
            ws = wb[sheet_name]

            # 批量写入
            for item in group_data:
                cell_ref = item["cell_ref"]
                value = item["value"]

                # 如果是元组列表（如 [(D10, 2779), (E10, 2719), ...]，表示横向列表
                if isinstance(value, list) and all(isinstance(v, tuple) and len(v) == 2 for v in value):
                    for cell, val in value:
                        ws[cell] = val
                else:
                    ws[cell_ref] = value
                    print(f"写入单元格 {cell_ref} 内容: {value}")

            output_path = path_manager.get_output_path(base_filename, sub_dir=sub_dir)
            wb.save(output_path)
            return f"成功写入 → {output_path}"

        except Exception as e:
            return f"写入失败[{sheet_name}] → 错误：{str(e)}"
    @staticmethod
    def _write_list_data(ws: Worksheet, value: list, target_cells: list, data_type: str):
        if len(value) != len(target_cells):
            raise ValueError(f"数据长度与目标单元格数量不匹配：{len(value)} vs {len(target_cells)}")

        if data_type == "list_horizontal":
            for cell_ref, val in zip(target_cells, value):
                ws[cell_ref] = val
        elif data_type == "list_vertical":
            for cell_ref, val in zip(target_cells, value):
                ws[cell_ref] = val
        else:
            raise ValueError(f"不支持的数据类型: {data_type}")
if __name__ == "__main__":
    #示例数据（直接包含待写入的value值）
    sample_data = [
        {
            "cell_ref": "B12",
            "value": "3243273.926",  # 直接写入的字符串值
            "sheet": "JS101"         # 对应templates/JS101.xlsx
        },
        {
            "cell_ref": "C5",
            "value": 509154.842,     # 直接写入的数值
            "sheet": "JS101"
        },
        {
            "cell_ref": "A3",
            "value": "浙江交工宏途交通建设有限公司",  # 直接写入的字符串
            "sheet": "JS202"         # 对应templates/JS202.xlsx
        }
    ]

    # 初始化写入器并执行写入
    writer = DirectTemplateWriter(sample_data)
    writer.write_all(max_workers=4, output_suffix="20240510")
